package com.tyq.client.security.access;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.FilterInvocation;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 自定义访问决策管理器(授权)
 *
 * @author 谭永强
 * @date 2024-05-31
 */
@Component
public class MyAccessDecisionManager implements AccessDecisionManager {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    /**
     * 为传递的参数解析访问控制决策
     *
     * @param authentication   身份验证
     * @param object           被调用的对象
     * @param configAttributes 与被调用的安全对象相关联的配置属性
     * @throws AccessDeniedException               如果由于身份验证没有所需的权限或ACL权限而拒绝访问
     * @throws InsufficientAuthenticationException 如果由于身份验证未提供足够的信任级别而拒绝访问
     */
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        FilterInvocation filterInvocation = (FilterInvocation) object;
        HttpServletRequest request = filterInvocation.getHttpRequest();
        Object principal = authentication.getPrincipal();
        if ("anonymousUser".equals(principal)) {
            logger.info("请求URI:{} - 未认证", request.getRequestURI());
            throw new InsufficientAuthenticationException("身份未认证!");
        }
        //根据当前用户信息查询API权限列表
        List<String> apiPermissionList = new ArrayList<>();
        apiPermissionList.add("/getCurrentUser");
        for (String uri : apiPermissionList) {
            if (antPathMatcher.match(uri, request.getRequestURI())) {
                logger.info("请求URI:{} - 访问权限:true", request.getRequestURI());
                return;
            }
        }
        logger.info("请求URI:{} - 访问权限:false", request.getRequestURI());
        throw new AccessDeniedException("没有访问权限!");
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
